<?php
/** 被访问者的接口，被访问者需要实现accept方法 */
interface Person
{
    /** @param Visitor $visitor */
    public function accept($visitor);
}
/** 访问者接口，需要实现访问各种被访问者的方法 */
interface Visitor
{
    /** @param Man $person */
    public function visitMan($person);
    /** @param Woman $person */
    public function visitWoman($person);
}

class Man implements Person
{
    public $type = "man";
    public function accept($visitor)
    {
        $visitor->visitMan($this);   
    }
    public $name = '';
    public function __construct($name)
    {
        $this->name = $name;
    }
}
class Woman implements Person
{
    public $type = "woman";
    public function accept($visitor)
    {
        $visitor->visitWoman($this);   
    }
    public $name = '';
    public function __construct($name)
    {
        $this->name = $name;
    }
}

class AVisitor implements Visitor
{
    public function visitMan($person)
    {
        echo "AVisitor::visitMan-{$person->type}-{$person->name}\r\n";
    }
    public function visitWoman($person)
    {
        echo "AVisitor::visitWoman-{$person->type}-{$person->name}\r\n";
    }
}

class ObjectStruct
{
    /** @var Person[] $list */
    public $list = [];
    /** @param Person $person */
    public function add($person)
    {
        $this->list[] = $person;
    }
    /** @param Visitor $visitor */
    public function exec($visitor)
    {
        foreach($this->list as $person){
            $person->accept($visitor);
        }
    }
}

header('Content-Type: text/plain');

$os = new ObjectStruct;
$os->add(new Man("John"));
$os->add(new Woman("Mary"));

$visitor = new AVisitor;
$os->exec($visitor);
